#!/usr/bin/env bash
# Usage: script/mirror update <COMMIT-RANGE>
#        script/mirror verify <COMMIT-RANGE>
#        script/mirror stats
set -e

eval "$(grep RUBY_BUILD_MIRROR_URL= ./bin/ruby-build | head -1)"

help_text() {
  sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' < "$0"
}

test_mirrored() {
  curl -qsSfIL "$RUBY_BUILD_MIRROR_URL/$1" >/dev/null 2>&1
}

compute_sha2() {
  local output="$(openssl dgst -sha256)"
  echo "${output##* }" | tr '[A-Z]' '[a-z]'
}

download_package() {
  curl -qsSfL -o "$2" "$1"
}

download_and_verify() {
  local checksum
  local url="$1"
  local file="$2"
  local expected="$3"
  download_package "$url" "$file"
  checksum="$(compute_sha2 < "$file")"
  if [ "$checksum" != "$expected" ]; then
    echo "Error: $url doesn't match its checksum $expected" >&2
    return 1
  fi
}

changed_files() {
  git diff --name-only --diff-filter=ACMR "$@"
}

potentially_new_packages() {
  local files="$(changed_files "$1" -- ./share/ruby-build)"
  [ -n "$files" ] && extract_urls $files
}

extract_urls() {
  $(type -p ggrep grep | head -1) -hoe 'http[^"]\+#[^"]\+' "$@" | sort | uniq
}

update() {
  local url
  local checksum
  local file
  for url in $(potentially_new_packages "$1"); do
    checksum="${url#*#}"
    url="${url%#*}"
    if test_mirrored "$checksum"; then
      echo "Already mirrored: $url"
    else
      echo "Mirroring: $url"
      file="${TMPDIR:-/tmp}/$checksum"
      download_and_verify "$url" "$file" "$checksum"
      ./script/s3-put "$file" "${AMAZON_S3_BUCKET?}"
    fi
  done
}

verify() {
  local url
  local checksum
  local file
  for url in $(potentially_new_packages "$1"); do
    checksum="${url#*#}"
    url="${url%#*}"
    echo "Verifying checksum for $url"
    file="${TMPDIR:-/tmp}/$checksum"
    download_and_verify "$url" "$file" "$checksum"
  done
}

stats() {
  local packages=( $(extract_urls ./share/ruby-build/*) )
  local total="${#packages[@]}"
  local confirmed=0
  local checksum
  for url in "${packages[@]}"; do
    checksum="${url#*#}"
    if test_mirrored "$checksum"; then
      confirmed="$((confirmed + 1))"
    else
      echo "failed: $url" >&2
    fi
    echo -n "."
  done
  echo
  echo "$confirmed/$total mirrored"
}

cmd="$1"

case "$cmd" in
update | verify | stats )
  shift 1
  "$cmd" "$@"
  ;;
-h | --help )
  help_text
  exit 0
  ;;
* )
  help_text >&2
  exit 1
  ;;
esac
